from PIL import Image
from StringIO import StringIO

# This function creates a PIL Image from raw image data.
def load_image_from_data(data):
    try:
        sio = StringIO(data)
        image = Image.open(sio)
    except Exception, e:
        raise Exception('Error loading image data, msg="%s"'%e.message)    
    return image
    
# This function extracts the raw image data from a PIL Image. 
def get_data_from_image(image, format = None):
    sio = StringIO()
    image.save(sio, format)
    return sio.getvalue()

# This function calculates the aspect maintaining size that the image
# should be resized to.
def adjust_size_to_maintain_aspect(original_size, desired_size):
    scale = float(desired_size[0])/original_size[0]
    if original_size[1] * scale <= desired_size[1]:
        height = int(original_size[1] * scale)
        if height > desired_size[1]:
            height = desired_size[1]
        return (desired_size[0], height)
    else:
        scale = float(desired_size[1])/original_size[1]
        width = int(original_size[0] * scale)
        if width > desired_size[0]:
            width = desired_size[0]
        return (width, desired_size[1])

# This function performs the actual image resizing.
def perform(image, size, maintain_aspect = True, method = Image.ANTIALIAS):
    # Load the image data into a PIL Image.
    pil_image = load_image_from_data(image)

    # If aspect must be maintained we need to find the correct 
    # size for the scaled image.
    if maintain_aspect:
        size = adjust_size_to_maintain_aspect(pil_image.size, size)
    
    # Scale the image.
    scaled_image = pil_image.resize(size, method)
    
    # Return the image data.
    return get_data_from_image(scaled_image, pil_image.format)
